﻿Imports Microsoft.VisualBasic
Imports System.Web
Imports System.Web.UI
Imports System.Web.UI.WebControls
Imports System.Text
Imports System.Text.RegularExpressions
Imports System.Threading

Namespace Utils
    Public Module LibGlobal


        Public Function GetDataLang(o As Object, Field As String) As String

            Dim t = o.GetType

            Dim Prop = t.GetProperty(Field & "_" & GetCurrLang(), Reflection.BindingFlags.Public Or Reflection.BindingFlags.Instance Or Reflection.BindingFlags.IgnoreCase)

            If Prop Is Nothing Then
                Prop = t.GetProperty(Field, Reflection.BindingFlags.Public Or Reflection.BindingFlags.Instance Or Reflection.BindingFlags.IgnoreCase)

            End If

            Return Prop.GetValue(o, Nothing)

        End Function

        Public Function GetCurrLang() As String

            Dim Lang = Thread.CurrentThread.CurrentCulture.TwoLetterISOLanguageName.ToUpper

            Return Lang


        End Function

        Public Function GetValue(ByRef r As Object, ByVal key As String) As String

            'If r(key) Is Nothing Then
            '    Return ""
            'Else
            Return Conv.ToStr(r(key))
            'End If

        End Function
        Public Function GetValueInt(ByRef r As Object, ByVal key As String) As Integer

            'If r(key) Is Nothing Then
            '    Return 0
            'Else
            Return Conv.ToInt(r(key))
            'End If

        End Function
        Public Function GetValueDbl(ByRef r As Object, ByVal key As String) As Double

            'If r(key) Is Nothing Then
            'Return 0
            'Else
            Return Conv.ToDouble(r(key))
            'End If

        End Function
        Public Function GetValueDate(ByRef r As Object, ByVal key As String) As Date

            Return Conv.ToDate(r(key), Date.MinValue)

        End Function


        Public Function GetObjectSize(ByRef o) As Integer
            Using s As IO.Stream = New IO.MemoryStream()
                Dim formatter As New Runtime.Serialization.Formatters.Binary.BinaryFormatter()
                formatter.Serialize(s, o)
                Return s.Length
            End Using
        End Function



        Public Function StringDup(Num As Integer, ByVal s As String) As String

            Dim tmp As String = ""
            For ct = 1 To Num
                tmp &= s
            Next

            Return tmp

        End Function


        Public Function ArrayToDictionary(ParamArray a() As Object) As Dictionary(Of String, Object)
            Dim d As New Dictionary(Of String, Object)

            For ct = 0 To a.Count - 1
                If ct Mod 2 = 0 Then
                    d.Add(a(ct), a(ct + 1))
                End If
            Next
            Return d

        End Function
        Public Function DictionaryToArray(dic As Dictionary(Of String, Object)) As Object()
            Dim a() As Object
            Dim ct As Integer = 0

            If dic Is Nothing Then
                Return Nothing
            End If

            ReDim a((dic.Count * 2) - 1)

            For Each d In dic
                a(ct) = d.Key
                a(ct + 1) = d.Value
                ct += 2
            Next

            Return a

        End Function
        Public Function ClearHTML(s) As String

            Return (Regex.Replace(s, "<[^>]*>", String.Empty, RegexOptions.IgnoreCase))

        End Function

    End Module
    Public Class List

        Public Shared Sub ToggleInt(ByRef l As List(Of Integer), v As Integer)

            If l Is Nothing Then
                l = New List(Of Integer)
            End If

            If l.Contains(v) Then
                l.Remove(v)
            Else
                l.Add(v)
            End If


        End Sub


    End Class

    Public Class Dictionary

        Public Shared Function GetValue(Of tkey, tvalue As {New})(d As Dictionary(Of tkey, tvalue), k As tkey) As tvalue

            If d.ContainsKey(k) Then
                Return d(k)
            Else
                Return New tvalue
            End If

        End Function

        Public Shared Function ConfigDictionary(ByVal ConfName As String) As Dictionary(Of String, String)

            Return StringToDictionary(System.Web.Configuration.WebConfigurationManager.AppSettings(ConfName))

        End Function

        Public Shared Function StringToDictionary(ByVal s As String) As Dictionary(Of String, String)
            Dim arr() As String = s.Split({";"}, StringSplitOptions.RemoveEmptyEntries)
            ' convert to a Dictionary
            Return arr.Select(Function(x) x.Split("=")).ToDictionary(Function(i) i(0), Function(i) i(1))
        End Function
    End Class
    Public Class MD5

        Public Shared Function MD5Compare(ByVal str As String, ByVal r As String) As Boolean

            Return MD5Create(str) = r

        End Function
        Public Shared Function MD5Create(ByVal str As String) As String

            Return MD5(str & "UrB1StaT2011")

        End Function
        Public Shared Function MD5(ByVal str As String) As String

            Dim md5Hasher As New System.Security.Cryptography.MD5CryptoServiceProvider

            Dim objUTF8 As New Text.UTF8Encoding

            Dim EncString As String = str

            Dim Encoder As New Text.UTF8Encoding

            Return BitConverter.ToString(md5Hasher.ComputeHash(Encoder.GetBytes(EncString))).Replace("-", Nothing)

        End Function

    End Class

    Public Class CRC32

        ' This is v2 of the VB CRC32 algorithm provided by Paul
        ' (wpsjr1@succeed.net) - much quicker than the nasty
        ' original version I posted.  Excellent work!

        Private crc32Table() As Integer
        Private Const BUFFER_SIZE As Integer = 1024

        Public Function GetCrc32(s As String) As Integer

            Dim ms As New System.IO.MemoryStream(UTF8Encoding.UTF8.GetBytes(s))

            Return Me.GetCrc32(ms)

        End Function

        Public Function GetCrc32(ByRef stream As System.IO.Stream) As Integer

            Dim crc32Result As Integer
            crc32Result = &HFFFFFFFF

            Dim buffer(BUFFER_SIZE) As Byte
            Dim readSize As Integer = BUFFER_SIZE

            Dim count As Integer = stream.Read(buffer, 0, readSize)
            Dim i As Integer
            Dim iLookup As Integer
            Dim tot As Integer = 0
            Do While (count > 0)
                For i = 0 To count - 1
                    iLookup = (crc32Result And &HFF) Xor buffer(i)
                    crc32Result = ((crc32Result And &HFFFFFF00) \ &H100) And &HFFFFFF   ' nasty shr 8 with vb :/
                    crc32Result = crc32Result Xor crc32Table(iLookup)
                Next i
                count = stream.Read(buffer, 0, readSize)
            Loop

            Return Not (crc32Result)

        End Function

        Public Sub New()

            ' This is the official polynomial used by CRC32 in PKZip.
            ' Often the polynomial is shown reversed (04C11DB7).
            Dim dwPolynomial As Integer = &HEDB88320
            Dim i As Integer, j As Integer

            ReDim crc32Table(256)
            Dim dwCrc As Integer

            For i = 0 To 255
                dwCrc = i
                For j = 8 To 1 Step -1
                    If (dwCrc And 1) Then
                        dwCrc = ((dwCrc And &HFFFFFFFE) \ 2&) And &H7FFFFFFF
                        dwCrc = dwCrc Xor dwPolynomial
                    Else
                        dwCrc = ((dwCrc And &HFFFFFFFE) \ 2&) And &H7FFFFFFF
                    End If
                Next j
                crc32Table(i) = dwCrc
            Next i
        End Sub

    End Class
    Public Class Conv

        Public Shared Function ToLong(ByVal o As Object, ByVal DefValue As Long) As Long
            Dim r As Long = DefValue

            Long.TryParse(CStr(o), r)
            Return r

        End Function
        Public Shared Function ToLong(ByVal o As Object) As Long
            Return ToLong(o, 0)
        End Function
        Public Shared Function ToInt(ByVal o As Object, ByVal DefValue As Integer) As Integer
            Dim r As Integer = DefValue

            If o Is DBNull.Value Or o Is Nothing Then
                Return r
            End If

            Integer.TryParse(o, r)
            Return r

        End Function
        Public Shared Function ToInt(ByVal o As Object) As Integer
            Return ToInt(o, 0)
        End Function
        Public Shared Function ToBool(ByVal o As Object, ByVal DefValue As Boolean) As Boolean
            Dim r As Boolean = DefValue

            If o Is DBNull.Value Or o Is Nothing Then
                Return r
            End If

            Boolean.TryParse(o, r)

            Return r

        End Function

        Public Shared Function ToDouble(ByVal o As Object, ByVal DefValue As Double) As Double
            Dim r As Double = DefValue

            If o Is DBNull.Value Or o Is Nothing Then
                Return r
            End If

            If o.GetType = GetType(String) Then
                Double.TryParse(CStr(o).Replace(".", ","), Globalization.NumberStyles.Number, Globalization.CultureInfo.CreateSpecificCulture("it"), r)
            Else
                Double.TryParse(o, Globalization.NumberStyles.Number, Globalization.CultureInfo.CreateSpecificCulture("it"), r)
            End If

            Return r

        End Function
        Public Shared Function ToDate(ByVal o As Object, ByVal DefValue As Date) As Date
            Dim r As Date = DefValue

            Date.TryParse(CStr(o), r)
            Return r

        End Function
        'Public Shared Function ToDateTime(ByVal o As Object, ByVal DefValue As DateTime) As DateTime
        '    Dim r As DateTime = DefValue

        '    DateTime.TryParse(CStr(o), r)
        '    Return r

        'End Function
        Public Shared Function ToTimeStamp(d As Date) As UInteger
            Dim TimeSpan = d.Subtract(New DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc))
            Return Convert.ToUInt32(TimeSpan.TotalSeconds)

        End Function

        Public Shared Function ToTimeStampDate(timestamp As UInteger) As Date

            Return ToTimeStampDate(timestamp, False)

        End Function
        Public Shared Function ToTimeStampDate(timestamp As Long, MillSec As Boolean) As Date

            If MillSec Then
                Return New DateTime(1970, 1, 1, 0, 0, 0, 0).AddMilliseconds(timestamp).ToLocalTime
            Else
                Return New DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc).AddSeconds(timestamp)
            End If

        End Function

        Public Shared Function ToDouble(ByVal o As Object) As Double
            Return ToDouble(o, 0)
        End Function
        Public Shared Function ToStr(ByVal o As Object) As String
            Return ToStr(o, "")
        End Function

        Public Shared Function ToStr(ByVal o As Object, ByVal DefValue As String) As String
            Dim r As String = ""

            If o Is DBNull.Value Or o Is Nothing Then
                Return r
            End If

            Return o.ToString

        End Function
        'Public Shared Function ToDateTime(ByVal o As Object) As DateTime
        '    Return ToDateTime(o, Nothing)
        'End Function
        Public Shared Function ToDate(ByVal o As Object) As Date
            Return ToDate(o, Nothing)
        End Function
        Public Shared Function ToBool(ByVal o As Object) As Boolean
            Return ToBool(o, False)
        End Function

        Public Shared Function ToTimeSpan(ByVal o As Object, ByVal DefValue As TimeSpan) As TimeSpan
            Dim r As TimeSpan = DefValue

            TimeSpan.TryParse(CStr(o), r)
            Return r

        End Function
        Public Shared Function ToTimeSpan(ByVal o As Object) As TimeSpan
            Dim d = ToTimeSpan(o, Nothing)

            Return d

        End Function


    End Class

    'Public Class Conv_old


    '    Public Shared Function ToLong(ByVal o As Object, ByVal DefValue As Long) As Long
    '        Try
    '            Return CType((IIf(IsDBNull(o), DefValue, o)), Long)
    '        Catch
    '            Return DefValue
    '        End Try
    '    End Function
    '    Public Shared Function ToLong(ByVal o As Object) As Long
    '        Return ToLong(o, 0)
    '    End Function

    '    Public Shared Function ToInt(ByVal o As Object, ByVal DefValue As Integer) As Integer
    '        Try
    '            Return CType((IIf(IsDBNull(o), DefValue, o)), Integer)
    '        Catch
    '            Return DefValue
    '        End Try
    '    End Function
    '    Public Shared Function ToInt(ByVal o As Object) As Integer
    '        Return ToInt(o, 0)
    '    End Function

    '    Public Shared Function ToBool(ByVal o As Object, ByVal DefValue As Boolean) As Boolean
    '        Try
    '            Return CType((IIf(IsDBNull(o), DefValue, o)), Boolean)
    '        Catch
    '            Return DefValue
    '        End Try
    '    End Function

    '    Public Shared Function ToDouble(ByVal o As Object, ByVal DefValue As Double) As Double
    '        Try
    '            If o.GetType Is GetType(String) Then
    '                Dim s As String
    '                s = DirectCast(o, String)
    '                s = s.Replace(".", ",")
    '                o = Double.Parse(s)
    '            End If
    '            Return CType((IIf(IsDBNull(o), DefValue, o)), Double)
    '        Catch
    '            Return DefValue
    '        End Try
    '    End Function

    '    Public Shared Function ToDate(ByVal o As Object, ByVal DefValue As Date) As Date
    '        Try
    '            Return CType((IIf(IsDBNull(o), DefValue, o)), Date)
    '        Catch
    '            Return DefValue
    '        End Try
    '    End Function

    '    Public Shared Function ToDateTime(ByVal o As Object, ByVal DefValue As DateTime) As DateTime
    '        Try
    '            Return CType((IIf(IsDBNull(o), DefValue, o)), DateTime)
    '        Catch
    '            Return DefValue
    '        End Try
    '    End Function


    '    Public Shared Function ToDouble(ByVal o As Object) As Double
    '        Return ToDouble(o, 0)
    '    End Function

    '    Public Shared Function ToStr(ByVal o As Object, ByVal DefValue As String) As String
    '        Return IIf(IsDBNull(o), DefValue, o.ToString).ToString
    '    End Function
    '    Public Shared Function ToStr(ByVal o As Object) As String
    '        Return IIf(IsDBNull(o), String.Empty, o.ToString).ToString
    '    End Function

    '    Public Shared Function ToDateTime(ByVal o As Object) As DateTime
    '        Return ToDateTime(o, Nothing)
    '    End Function



    '    Public Shared Function ToDate(ByVal o As Object) As Date
    '        Return ToDate(o, Nothing)
    '    End Function

    '    Public Shared Function ToBool(ByVal o As Object) As Boolean
    '        Return ToBool(o, False)
    '    End Function


    'End Class

    Public Class Color

        Public Shared Function ToRGB(ByVal c As Drawing.Color) As String

            Return Drawing.ColorTranslator.ToHtml(c).Trim(New Char() {"#"})

        End Function
        Public Shared Function ToARGB(ByVal c As Drawing.Color) As String

            'Return Format(Hex(c.A), "00") & Drawing.ColorTranslator.ToHtml(c).Trim(New Char() {"#"})
            Return c.Name

        End Function
        Public Shared Function ToABGR(ByVal c As Drawing.Color) As String

            Return Format(c.A, "X2") & Format(c.B, "X2") & Format(c.G, "X2") & Format(c.R, "X2")

        End Function

        Public Shared Function ToCol(ByVal c As String) As Drawing.Color

            If c = "" Then
                Return Drawing.ColorTranslator.FromHtml("#FFFFFF")
            Else
                Return Drawing.ColorTranslator.FromHtml("#" & c.Trim(New Char() {"#"}))
            End If

        End Function
        Public Shared Function ToCol(ByVal c As String, ByVal t As Integer) As Drawing.Color
            Dim ctmp As Drawing.Color = ToCol(c)

            Return Drawing.Color.FromArgb(t, ctmp.R, ctmp.G, ctmp.B)

        End Function
        Public Shared Function RndCol() As Drawing.Color

            Randomize()
            Return Drawing.Color.FromArgb(Int(Rnd() * 256), Int(Rnd() * 256), Int(Rnd() * 256))

        End Function

    End Class

    Public Class Math

        Public Shared Function Perc(ByVal a As Object, ByVal b As Object) As Object

            If a Is DBNull.Value Or b Is DBNull.Value Then
                Return DBNull.Value
            End If

            Return Div(a, b) * 100

        End Function
        Public Shared Function Div(ByVal a As Object, ByVal b As Object) As Object

            If a Is DBNull.Value Or b Is DBNull.Value Then
                Return DBNull.Value
            End If

            If b = 0 Then
                Return 0
            Else
                Return a / b
            End If

        End Function
        Public Shared Function LevelFromValue(ByVal b As Double, ByVal e As Double, ByVal TotLvl As Integer, ByVal value As Double) As Integer

            'Return b + ((e - b) / (TotLvl) * (CurrLvl))

            'Return (value - b) / ((e - b) / (TotLvl))
            Return Int((value - b) / ((e - b + 1) / (TotLvl))) + 1

        End Function

        Public Shared Function ValueFromLevels(ByVal b As Double, ByVal e As Double, ByVal TotLvl As Integer, ByVal CurrLvl As Integer) As Double

            Return b + ((e - b) / (TotLvl) * (CurrLvl))

        End Function
        Public Shared Function ValueFromLevelsExp(ByVal b As Double, ByVal e As Double, ByVal TotLvl As Integer, ByVal CurrLvl As Integer, Exp As Double) As Double
            'e = System.Math.Log(e, 2)
            e = e ^ (1 / Exp)
            b = b ^ (1 / Exp)

            Return (b + ((e - b) / (TotLvl) * (CurrLvl))) ^ Exp

        End Function

        Public Shared Function DegToRad(ByRef deg As Double)
            Return (deg / 180.0 * System.Math.PI)
        End Function

        Public Shared Function RadToDeg(ByRef rad As Double)
            Return (rad / System.Math.PI * 180.0)
        End Function

        Public Shared Function GetYFromPoints(p1 As Drawing.PointF, p2 As Drawing.PointF, x As Double) As Double
            Dim c As Double = (p2.Y - p1.Y) / (p2.X - p1.X)

            Return p1.Y + ((x - p1.X) * c)

        End Function
        Public Shared Function GetXFromPoints(p1 As Drawing.PointF, p2 As Drawing.PointF, y As Double) As Double
            Dim c As Double = (p2.X - p1.X) / (p2.Y - p1.Y)

            Return p1.X + ((y - p1.Y) * c)

        End Function
        Public Shared Function DoubleComp(d As Double) As Double

            Return System.Math.Round(d, 5)

        End Function

    End Class

    Public Class DT

        Public Shared Sub SetData(ByRef dt As DataTable, ByVal c As String, ByVal d As Object)

            SetData(dt, dt.Rows.Count - 1, c, d)

        End Sub
        Public Shared Sub SetData(ByRef dt As DataTable, ByVal r As Integer, ByVal c As String, ByVal d As Object)

            dt.Rows(r)(c) = d

        End Sub
        Public Shared Sub AddDataRow(ByRef dt As DataTable, ByVal ParamArray d() As Object)
            Dim dr = dt.NewRow

            SetDataRow(dr, d)

            dt.Rows.Add(dr)

        End Sub
        Public Shared Sub AddDataRowAt(ByRef dt As DataTable, ByVal r As Integer, ByVal ParamArray d() As Object)
            Dim dr = dt.NewRow

            SetDataRow(dr, d)

            dt.Rows.InsertAt(dr, r)

        End Sub

        Public Shared Sub SetDataRow(ByRef dr As DataRow, ByVal ParamArray d() As Object)
            Dim tmp As Object

            'For ct = 0 To d.Length - 1
            '    If d(ct) IsNot Nothing Then
            '        tmp = d(ct)
            '        If d(ct).GetType Is GetType(String) Then
            '            If Left(d(ct), 1) = "=" Then
            '                tmp = dr.Table.Compute(d(ct).ToString.Substring(1), "")
            '            End If
            '        End If
            '        dr(ct) = tmp
            '    End If
            'Next

            For ct = 0 To d.Length - 1 Step 2
                tmp = d(ct + 1)
                If d(ct + 1).GetType Is GetType(String) Then
                    If Left(d(ct + 1), 1) = "=" Then
                        tmp = dr.Table.Compute(d(ct + 1).ToString.Substring(1), "")
                    End If
                End If
                dr(d(ct)) = tmp
            Next

        End Sub
        Public Shared Sub SetDataRow(ByRef dt As DataTable, ByVal ParamArray d() As Object)

            SetDataRow(dt.Rows(dt.Rows.Count - 1), d)

        End Sub
        Public Shared Sub SetDataRow(ByVal dt As DataTable, ByVal r As Integer, ByVal ParamArray d() As Object)

            SetDataRow(dt.Rows(r), d)

        End Sub
        Public Shared Sub RemoveRow(ByRef dt As DataTable, ByVal r As Integer)

            dt.Rows.RemoveAt(r)

        End Sub
        Public Shared Sub RemoveRow(ByRef dt As DataTable)

            dt.Rows.RemoveAt(dt.Rows.Count - 1)

        End Sub
        Public Shared Function ToListDT(ByRef dt As DataTable, ByVal NumList As Integer) As List(Of Object)
            Dim L As New List(Of Object)

            Dim num_per_box = System.Math.Round((CInt(dt.Rows.Count) / NumList) + 0.499)

            Dim dt_temp As DataTable = dt.Clone

            For ct As Integer = 0 To dt.Rows.Count - 1
                dt_temp.ImportRow(dt.Rows(ct))
                If (ct + 1) Mod num_per_box = 0 Or ct + 1 = dt.Rows.Count Then
                    L.Add(New With {.dt = dt_temp})
                    dt_temp = dt.Clone
                End If
            Next

            Return L

        End Function
        Public Shared Function ToDictionary(Of TKey)(ByRef dt As DataTable, KeyField As String) As Dictionary(Of TKey, DataRow)

            Dim r As New Dictionary(Of TKey, DataRow)
            Dim k As TKey

            For Each dr As DataRow In dt.Rows
                k = dr(KeyField)
                If Not r.ContainsKey(k) Then
                    r.Add(k, dr)
                End If
            Next

            Return r

        End Function

        Public Shared Function ToObj(Of tres)(dr As DataRowView) As tres

            Return ToObj(Of tres)(dr.Row)

        End Function
        Public Shared Function ToObj(Of tres)(dr As DataRow) As tres

            Dim t = GetType(tres)
            Dim PropList = DBase.Data.GetListPropObjectDataTable(dr.Table, t)
            Dim info As Reflection.ConstructorInfo = t.GetConstructor(New Type() {})

            Dim obj As tres = info.Invoke(Nothing)

            DBase.Data.DataRowToObject(dr, obj, PropList)


            Return obj

        End Function

        Public Shared Function ToList(Of TResultf)(ByRef dt As DataTable, FieldObj As String) As List(Of TResultf)

            Dim t = GetType(TResultf)
            Dim obj As TResultf
            Dim r As New List(Of TResultf)


            If Not t.IsValueType And t <> GetType(String) Then
                Dim PropList = DBase.Data.GetListPropObjectDataTable(DT, t)
                Dim info As Reflection.ConstructorInfo = t.GetConstructor(New Type() {})

                For Each dr As DataRow In DT.Rows
                    obj = info.Invoke(Nothing)
                    'obj = New TResultf
                    DBase.Data.DataRowToObject(dr, obj, PropList)
                    r.Add(obj)
                Next

            Else
                Dim Field As String

                If FieldObj = "" Then
                    Field = DT.Columns(0).ColumnName
                Else
                    Field = FieldObj
                End If

                If t = GetType(DateTime) Then
                    For Each dr As DataRow In DT.Rows
                        Dim d As Object = Date.MinValue
                        If dr(Field).year <> 0 Then
                            d = Convert.ChangeType(dr(Field), GetType(DateTime))
                        End If
                        r.Add(d)
                    Next

                Else
                    For Each dr As DataRow In DT.Rows
                        If dr(Field) IsNot DBNull.Value Then
                            r.Add(dr(Field))
                        End If
                    Next

                End If


            End If


            Return r

        End Function

        Public Shared Function ToArrayList(ByRef dt As DataTable) As List(Of Object())

            Dim DataList = (From a As DataRow In dt.Rows Select a.ItemArray).ToList
            DataList.Insert(0, (From c As DataColumn In dt.Columns Select c.Caption).ToArray)


            Return DataList

        End Function


        'Public Shared Function ToList(Of TKey)(ByRef dt As DataTable, KeyField As String) As List(Of TKey)

        '    Dim r As New List(Of TKey)
        '    Dim k As TKey

        '    For Each dr As DataRow In dt.Rows
        '        k = dr(KeyField)
        '        r.Add(k)
        '    Next

        '    Return r

        'End Function
        'Public Function ToList(Of TResultf As {New, Class})(ByRef dt As DataTable) As List(Of TResultf)

        '    Dim t = GetType(TResultf)
        '    Dim obj As TResultf
        '    Dim r As New List(Of TResultf)


        '    Dim PropList = DBase.Data.GetListPropObjectDataTable(DT, t)

        '    For Each dr As DataRow In DT.Rows
        '        obj = New TResultf
        '        DBase.Data.DataRowToObject(dr, obj, PropList)
        '        r.Add(obj)
        '    Next

        '    Return r

        'End Function

        'Public Shared Sub VariationColumnAdd(ByRef dt As DataTable, ByVal Field As String, ByVal RefField As String)

        '    dt.Columns.Add(Field, GetType(Double))
        '    'dt.Rows(0)(Field) = 0
        '    For ct As Integer = 1 To dt.Rows.Count - 1
        '        dt.Rows(ct)(Field) = Utils.Math.Perc(dt.Rows(ct)(RefField), dt.Rows(ct - 1)(RefField)) - 100
        '    Next

        'End Sub
        'Public Shared Sub PercColumnAdd(ByRef dt As DataTable, ByVal Field As String, ByVal RefField As String, ByVal RefValue As Double)

        '    dt.Columns.Add(Field, GetType(Double))
        '    'dt.Rows(0)(Field) = 0
        '    For ct As Integer = 0 To dt.Rows.Count - 1
        '        dt.Rows(ct)(Field) = Utils.Math.Perc(dt.Rows(ct)(RefField), RefValue)
        '    Next

        'End Sub
        'Public Shared Sub TotalRowAdd(ByRef dt As DataTable, ByVal Fields() As String)
        '    Dim rr As DataRow

        '    rr = dt.NewRow
        '    For ctc As Integer = 0 To Fields.Length - 1
        '        rr.Item(Fields(ctc)) = 0
        '        For ctr As Integer = 0 To dt.Rows.Count - 1
        '            rr.Item(Fields(ctc)) += Utils.Conv.ToDouble(dt.Rows(ctr).Item(Fields(ctc)))
        '        Next
        '    Next
        '    dt.Rows.Add(rr)

        'End Sub
        'Public Shared Sub CumulateColumnAdd(ByRef dt As DataTable, ByVal Field As String, ByVal RefField As String)

        '    Dim Tot As Double = 0
        '    dt.Columns.Add(Field, GetType(Double))
        '    For ct As Integer = 0 To dt.Rows.Count - 1
        '        Tot += Utils.Conv.ToDouble(dt.Rows(ct).Item(RefField))
        '        dt.Rows(ct)(Field) = Tot
        '    Next

        'End Sub
        Public Shared Sub Transposition(ByRef Dr As DataRow, BeginFieldPos As Integer, NumField As Integer, ByRef dt As DataTable, FieldName As String, BeginRow As Integer)

            For ct = 0 To NumField - 1
                dt.Rows(BeginRow + ct)(FieldName) = Dr(BeginFieldPos + ct)
            Next

        End Sub
        Public Shared Function Clone(ByRef dt As DataTable) As DataTable
            Dim d = dt.Clone

            For Each dr As DataRow In dt.Rows
                d.Rows.Add(dr.ItemArray)
            Next

            Return d

        End Function

        Public Shared Function GetYFromSerie(dt As DataTable, xField As String, yField As String, x As Double) As Double

            For ct = 0 To dt.Rows.Count - 2
                If dt.Rows(ct)(xField) <= x And dt.Rows(ct + 1)(xField) >= x Then
                    Return Utils.Math.GetYFromPoints(
                        New Drawing.PointF(dt.Rows(ct)(xField), dt.Rows(ct)(yField)),
                        New Drawing.PointF(dt.Rows(ct + 1)(xField), dt.Rows(ct + 1)(yField)),
                        x)
                End If
            Next
            Return 0

        End Function
        Public Shared Function GetXFromSerie(dt As DataTable, xField As String, yField As String, y As Double) As Double

            For ct = 0 To dt.Rows.Count - 2
                If dt.Rows(ct)(yField) <= y And dt.Rows(ct + 1)(yField) >= y Then
                    Return Utils.Math.GetXFromPoints(
                        New Drawing.PointF(dt.Rows(ct)(xField), dt.Rows(ct)(yField)),
                        New Drawing.PointF(dt.Rows(ct + 1)(xField), dt.Rows(ct + 1)(yField)),
                        y)
                End If
            Next
            Return 0

        End Function
        Public Shared Sub JoinData(Of TKey)(ByRef DtFrom As DataTable, ByRef DtJoin As DataTable, KeyFrom As String, KeyJoin As String, FieldsJoin() As String)

            Dim Fields As New List(Of DBase.SqlField)

            For Each f In FieldsJoin
                Fields.Add(DBase.Conv.FieldToAlias(f))
            Next


            'FieldToAlias
            ' aggiungo la scruttura nella destinazione
            For Each f In Fields
                DtFrom.Columns.Add(f.Alias, DtJoin.Columns(f.Name).DataType)
            Next

            ' trasforma la tabella del join in un dictionary con chiave il capo su cui fare il join

            Dim JoinDic = ToDictionary(Of TKey)(DtJoin, KeyJoin)

            'JoinData(Of TKey)(JoinDic, DtDest, KeyDest, FieldsSource)

            'Dim jj = (From Row In DtSorg Join row2 In DtDest On Row("") Equals row2(""))



            ''scorre tutte le righe della tabella
            For Each Row In DtFrom.Rows
                'per ogni riga si prende la riga della join che ha come chiave il valore del campo della join
                If JoinDic.ContainsKey(Row(KeyFrom)) Then
                    Dim LinkRow = JoinDic(Row(KeyFrom))
                    'aggiungono ad ogni riga tutti campi della tabella di join
                    For Each Field In Fields
                        Row(Field.Alias) = LinkRow(Field.Name)
                    Next

                End If

            Next

        End Sub
        'Public Shared Sub JoinData(Of TKey)(ByRef DicSorg As Dictionary(Of TKey, DataRow), ByRef DtDest As DataTable, KeyDest As String, FieldsSource() As String)

        '    Dim DtSorg = DicSorg.First.Value.Table

        '    ' aggiungo la scruttura nella destinazione
        '    For Each f In FieldsSource
        '        DtDest.Columns.Add(f, DtSorg.Columns(f).DataType)
        '    Next

        '    'scorre tutte le righe della tabella
        '    For Each Row In DtDest.Rows
        '        'per ogni riga si prende la riga della join che ha come chiave il valore del campo della join
        '        If DicSorg.ContainsKey(Row(KeyDest)) Then
        '            Dim LinkRow = DicSorg(Row(KeyDest))
        '            'aggiungono ad ogni riga tutti campi della tabella di join
        '            For Each Field In FieldsSource
        '                Row(Field) = LinkRow(Field)
        '            Next

        '        End If

        '    Next

        'End Sub


        'Public Sub JoinData2(DtSorg As DataTable, DtDest As DataTable, KeysSource() As String, KeysDest() As String, FieldsSource() As String, FieldsDest() As String)

        '    ' TODO
        '    For Each f In FieldsDest
        '        DtDest.Columns.Add(f, DtSorg.Columns(f).DataType)
        '    Next

        '    For Each drs In DtSorg.Rows

        '        For Each drd In DtDest.Rows
        '            If drd(KeysDest(0)) = drd(KeysSource(0)) Then
        '                For Each f In FieldsDest
        '                    DtDest.Columns.Add(f, DtSorg.Columns(f).DataType)
        '                Next
        '            End If

        '        Next
        '    Next



        '    'DT.Columns.Add(Field, Me.FieldType)

        'End Sub
        Public Class ComputeData

            Public Enum HowComputeType
                Column
                Row
            End Enum

            Public dt As DataTable
            Public Exp As String
            Public HowCompute As HowComputeType

            'elaborazione per colonna
            Public Field As String
            Public FieldType As Type

            'elaborazione per riga
            Public RowPos As Integer
            Public BeginFieldPos As Integer
            Public NumField As Integer

            Private Vars As New List(Of Variable)
            Private p() As Object

            Public Shared Function Compute(ByRef dt As DataTable, ByVal Field As String, ByVal Exp As String, ByVal ParamArray p() As Object) As DataTable

                Return Compute(dt, Field, GetType(Double), Exp, p)

            End Function
            Public Shared Function Compute(ByRef dr As DataRow, ByVal Field As String, ByVal Exp As String, ByVal ParamArray p() As Object) As Object

                Return Compute(dr.Table, Field, GetType(Double), Exp, p).Rows(0)(Field)

            End Function

            Public Shared Function Compute(ByRef dt As DataTable, ByVal Field As String, ByVal t As Type, ByVal Exp As String, ByVal ParamArray p() As Object) As DataTable

                Dim CD = New ComputeData With {
                    .dt = dt,
                    .Exp = Exp,
                    .Field = Field,
                    .p = p,
                    .FieldType = t,
                    .HowCompute = HowComputeType.Column
                }

                CD.ComputeVars()

                Return dt

            End Function

            Public Shared Sub ComputeRow(ByRef dt As DataTable, BeginFieldPos As Integer, NumField As Integer, ByVal Exp As String, ByVal ParamArray p() As Object)

                ComputeRow(dt, dt.Rows.Count - 1, BeginFieldPos, NumField, Exp, p)

            End Sub

            Public Shared Sub ComputeRow(ByRef dt As DataTable, ByVal RowPos As Integer, BeginFieldPos As Integer, NumField As Integer, ByVal Exp As String, ByVal ParamArray p() As Object)

                Dim CD = New ComputeData With {
                    .dt = dt,
                    .Exp = Exp,
                    .RowPos = RowPos,
                    .BeginFieldPos = BeginFieldPos,
                    .NumField = NumField,
                    .p = p,
                    .HowCompute = HowComputeType.Row
                }

                CD.ComputeVars()

                'Compute(dt, Field, GetType(Double), Exp, p)

            End Sub

            Public Sub ExpToVars()
                '"( {'datavalue'} / {'datavalue';-1} * 100 ) -100"

                Dim r As New Regex("\{([^\},\{]+)\}")
                Dim xy() As String
                Dim v As Variable

                'ricerca i parametri
                Dim mc = r.Matches(Me.Exp)
                'resetta tutte le var
                Me.Vars.Clear()

                'sostituisce i parametri utenti calcolati
                For ct = 0 To Me.p.Length - 1 Step 2
                    If p(ct).GetType Is GetType(String) Then
                        If Left(p(ct), 1) = "=" Then
                            p(ct) = Me.dt.Compute(p(ct).ToString.Substring(1), "")
                        End If
                    End If
                Next

                For Each m As RegularExpressions.Match In mc

                    xy = m.Value.Substring(1, m.Value.Length - 2).Split(";")

                    If Left(xy(0), 1) = "p" Then
                        Me.Exp = Me.Exp.Replace(m.Value, UI.Print.NumStr(Me.p(xy(0).Substring(1)).ToString))
                    Else
                        v = New Variable
                        v.Label = m.Value

                        If Left(xy(0), 1) = "'" Then
                            v.AbsoluteX = Me.dt.Columns.IndexOf(xy(0).Substring(1, xy(0).Length - 2))
                        Else
                            If Left(xy(0), 1) = "$" Then
                                v.AbsoluteX = Utils.Conv.ToInt(xy(0).Substring(1))
                            Else
                                v.OffsetX = Utils.Conv.ToInt(xy(0))
                            End If

                        End If

                        If xy.Length > 1 Then
                            If Left(xy(1), 1) = "'" Then
                                v.AbsoluteY = Me.dt.Columns.IndexOf(xy(1).Substring(1, xy(1).Length - 2))
                            Else
                                If Left(xy(1), 1) = "$" Then
                                    v.AbsoluteY = Utils.Conv.ToInt(xy(1).Substring(1))
                                Else
                                    v.OffsetY = Utils.Conv.ToInt(xy(1))
                                End If

                            End If

                        End If

                        Me.Vars.Add(v)
                    End If



                Next


            End Sub
            'Public Sub ComputeVarsRow()
            '    Dim ColX, ColY As Integer
            '    Dim BaseX, BaseY As Integer
            '    Dim ValueVars() As String

            '    '----------------------------------
            '    'init value
            '    Me.ExpToVars()

            '    Dim TmpExp As String = Me.Exp
            '    For ct As Integer = 0 To Me.Vars.Count - 1
            '        TmpExp = TmpExp.Replace(Me.Vars(ct).Label, "{" & ct.ToString & "}")
            '    Next
            '    'init value
            '    '----------------------------------

            '    BaseY = RowPos

            '    For ct As Integer = 0 To NumField - 1
            '        BaseX = ct + BeginFieldPos

            '        '----------------------------------
            '        'getvalue
            '        For ctv As Integer = 0 To Vars.Count - 1

            '            ColX = Vars(ctv).AbsoluteX
            '            If ColX < 0 Then
            '                ColX = BaseX + Vars(ctv).OffsetX
            '            End If
            '            ColY = Vars(ctv).AbsoluteY
            '            If ColY < 0 Then
            '                ColY = BaseY + Vars(ctv).OffsetY
            '            End If

            '            Try
            '                Vars(ctv).Value = UI.Print.NumStr(dt.Rows(ColY)(ColX))
            '            Catch ex As Exception
            '                Vars(ctv).Value = 0
            '            End Try

            '        Next
            '        'getvalue
            '        '----------------------------------

            '        ValueVars = Vars.Select(Of String)(Function(o) o.Value).ToArray
            '        Try
            '            dt.Rows(BaseY)(BaseX) = dt.Compute(String.Format(TmpExp, ValueVars), "")
            '        Catch ex As Exception
            '            dt.Rows(BaseY)(BaseX) = DBNull.Value
            '        End Try

            '    Next


            'End Sub

            Public Sub ComputeVars()
                Dim ColX, ColY As Integer
                Dim BaseX, BaseY, NumCell As Integer
                Dim ValueVars() As String
                Dim DtVal As New DataTable

                Me.ExpToVars()

                'Exit Sub

                Dim TmpExp As String = Me.Exp
                For ct As Integer = 0 To Me.Vars.Count - 1
                    TmpExp = TmpExp.Replace(Me.Vars(ct).Label, "{" & ct.ToString & "}")
                Next

                If Me.HowCompute = HowComputeType.Column Then
                    If Not dt.Columns.Contains(Field) Then
                        dt.Columns.Add(Field, Me.FieldType)
                    End If
                    BaseX = dt.Columns.IndexOf(Field)
                    NumCell = dt.Rows.Count
                Else
                    If Me.RowPos = -1 Then
                        dt.Rows.Add(dt.NewRow)
                        RowPos = dt.Rows.Count - 1
                    End If
                    BaseY = RowPos
                    NumCell = NumField
                End If


                For ct As Integer = 0 To NumCell - 1

                    If Me.HowCompute = HowComputeType.Column Then
                        BaseY = ct
                    Else
                        BaseX = ct + BeginFieldPos
                    End If

                    For ctv As Integer = 0 To Vars.Count - 1

                        ColX = Vars(ctv).AbsoluteX
                        If ColX < 0 Then
                            ColX = BaseX + Vars(ctv).OffsetX
                        End If
                        ColY = Vars(ctv).AbsoluteY
                        If ColY < 0 Then
                            ColY = BaseY + Vars(ctv).OffsetY
                        End If

                        'Try
                        If ColY < 0 Or ColX < 0 Then
                            Vars(ctv).Value = 0
                        Else

                            If dt.Rows(ColY)(ColX) Is DBNull.Value Then
                                Vars(ctv).Value = "0"
                            Else
                                Vars(ctv).Value = UI.Print.NumStr(dt.Rows(ColY)(ColX))
                            End If

                        End If
                        'Catch ex As Exception
                        'End Try

                    Next

                    ValueVars = Vars.Select(Of String)(Function(o) o.Value).ToArray
                    'Try
                    'dt.Rows(BaseY)(BaseX) = 0
                    dt.Rows(BaseY)(BaseX) = DtVal.Compute(String.Format(TmpExp, ValueVars), "")
                    'Catch ex As Exception
                    '    DT.Rows(BaseY)(BaseX) = DBNull.Value
                    'End Try

                Next


            End Sub

            Private Class Variable

                Public OffsetX As Integer = 0
                Public OffsetY As Integer = 0
                Public AbsoluteX As Integer = -1
                Public AbsoluteY As Integer = -1
                Public Label As String
                Public Value As String

            End Class
        End Class

    End Class

    Public Class GC

        Public Shared Sub WaitFinalizers()
            System.GC.Collect(System.GC.MaxGeneration)
            System.GC.WaitForPendingFinalizers()
        End Sub


    End Class

    Namespace Threading


        Public Class ThreadsManage
            Private NumThread As Integer
            Private Threads() As Thread

            'Private Const MemTread = 1024 * 1024 * 100

            Public Sub New(NumThread As Integer)
                Me.NumThread = NumThread
                ReDim Threads(NumThread - 1)



            End Sub

            Public Sub Start(Thread As ParameterizedThreadStart, params As Object)
                Dim trovato As Boolean

                trovato = False
                Do

                    For ct = 0 To NumThread - 1
                        If Threads(ct) Is Nothing Then
                            trovato = True
                        ElseIf Not Threads(ct).IsAlive Then
                            trovato = True
                        End If

                        If trovato Then
                            Threads(ct) = New Thread(Thread)

                            Threads(ct).Start(params)
                            Exit For
                        End If
                    Next
                Loop Until trovato

            End Sub
            Public Sub WaitEnd()

                Dim finito = True
                Do
                    finito = True
                    For ct = 0 To NumThread - 1
                        If Threads(ct) IsNot Nothing Then
                            If Threads(ct).IsAlive Then
                                finito = False
                                Exit For
                            End If
                        End If
                    Next

                Loop Until finito

            End Sub


        End Class


    End Namespace



End Namespace
